/*!	 widthpoint.cpp
**	 Template File for a Width Point implementation
**
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
**	Copyright (c) 2010 Carlos López
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**
*/

#ifdef USING_PCH
#	include "pch.h"
#else
#ifdef HAVE_CONFIG_H
#	include <config.h>
#endif

#include <cmath>
#include "widthpoint.h"

#endif

using namespace std;
using namespace synfig;

WidthPoint::WidthPoint():
    position_(0.0),
    width_(0.01),
    dash_(false),
    lower_bound_(0.0),
    upper_bound_(1.0)
{
    side_type_[0] = side_type_[1] = TYPE_INTERPOLATE;
}

WidthPoint::WidthPoint(Real position, Real width, int sidebefore, int sideafter, bool dash):
    position_(position),
    width_(width)
{
    side_type_[0] = sidebefore;
    side_type_[1] = sideafter;
    dash_ = dash;
    lower_bound_ = 0.0;
    upper_bound_ = 1.0;
}

const Real&
WidthPoint::get_position()const
{
    return position_;
}

Real
WidthPoint::get_norm_position(bool wplistloop)const
{
    return (get_bound_position(wplistloop) - lower_bound_) / (upper_bound_ - lower_bound_);
}

Real
WidthPoint::get_bound_position(bool wplistloop)const
{
    Real ret(position_ - lower_bound_);
    Real range(upper_bound_ - lower_bound_);

    if (!wplistloop) {
        if (ret < 0) {
            ret = 0;
        }

        if (ret > range) {
            ret = range;
        }
    } else {
        ret = fmod(ret, range);
        ret = ret >= 0.0 ? ret : (range + ret);
    }

    return ret + lower_bound_;
}

void
WidthPoint::normalize(bool loop)
{
    set_position(get_norm_position(loop));
}

void
WidthPoint::reverse()
{
    position_ = upper_bound_ - (position_ - lower_bound_);
}

void
WidthPoint::set_position(const Real& x)
{

    position_ = x;
}

const Real&
WidthPoint::get_width()const
{
    return width_;
}

void
WidthPoint::set_width(Real x)
{
    width_ = x;
}

int
WidthPoint::get_side_type_before()const
{
    return side_type_[0];
}

void
WidthPoint::set_side_type_before(int sidebefore)
{
    side_type_[0] = sidebefore;
}

int
WidthPoint::get_side_type_after()const
{
    return side_type_[1];
}

void
WidthPoint::set_side_type_after(int sideafter)
{
    side_type_[1] = sideafter;
}

int
WidthPoint::get_side_type(int i)const
{
    return i > 0 ? side_type_[1] : side_type_[0];
}

void
WidthPoint::set_dash(bool l)
{
    dash_ = l;
}

bool
WidthPoint::get_dash()const
{
    return dash_;
}

void
WidthPoint::set_lower_bound(Real lb)
{
    lower_bound_ = lb;
}

Real
WidthPoint::get_lower_bound()const
{
    return lower_bound_;
}

void
WidthPoint::set_upper_bound(Real ub)
{
    upper_bound_ = ub;
}

Real
WidthPoint::get_upper_bound()const
{
    return upper_bound_;
}

bool
WidthPoint::operator<(const WidthPoint& rhs)
{
    return get_position() < rhs.get_position();
}

bool
WidthPoint::operator == (const WidthPoint& rhs)
{
    return 	side_type_[0] == rhs.get_side_type(0) &&
            side_type_[1] == rhs.get_side_type(1) &&
            position_ == rhs.get_position() &&
            width_ == rhs.get_width() &&
            lower_bound_ == rhs.get_lower_bound() &&
            upper_bound_ == rhs.get_upper_bound()
            ;
}